剛學JS的我在codewars上做了一個難度7kyu的題目
題目為 Exes and Ohs
連結如下https://www.codewars.com/kata/exes-and-ohs/javascript
題目是判斷OX的數量是否相等
如果一樣回傳true,不同則false,沒有半個OX也會是true。
好不容易用split解出來後,結果被同學用reduce的解法給驚豔到!
特別寫這篇來記錄一下
解法是用devdocs.io內介紹的一種reduce用法
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) { //如果name這個 Key已經有在allNames裡面了的話
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
出處https://devdocs.io/javascript/global_objects/array/reduce
內的Counting instances of values in an object
裡面的reduce先把allNames設為一個Object,之後用if判斷name這個Key在不在allNames裡面,再去做object給值的動作。
這招沒想到可以用在OX題目上面啊!
上面reduce的結果我用兩種for迴圈再寫了一遍
var ary = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var alname = {}; //存放的Object
//第一種普通的for迴圈寫法
function forFoReduce(ary1){
for(var i = 0 ; i < ary1.length ; i++){
//判斷alname的ary1[i]這個 Key的Value是不是NaN,是的話等於一
if(isNaN( alname[ary1[i]] )){
alname[ary1[i]] = 1;
}
else {
alname[ary1[i]]++; //已經等於1了的話就再+1
}
}
return alname;
}
//第二種for迴圈寫法
function forFoReduce2(ary1){
//item是ary1每個陣列內容,就像是上面for迴圈的ary1[i]
for(let item of ary1) {
if(isNaN( alname[item] )){ //把item當作alname的 Key放進去比對
alname[item] = 1; //Key內的Value是NaN的話就 = 1
}
else {
alname[item]++; //已經找到過了就再加一
}
}
return alname;
}
以上介紹的三種方法都會產出:
{ 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
了解到這些解法的話再來挑戰一次OX題目吧!
以下私心用for of方式下去解
function XO(str) {
//因為題目給的是字串且有大小寫問題,所以用toUpperCase都先轉成大寫,再用split('')轉成陣列型態。
var ary = str.toUpperCase().split('');
var alname = {}; //宣告一個空的Object
for(let item of ary) {
//如果alname裡面的item這個 Key的Value是NaN的話,等於一
if(isNaN( alname[item] )){
alname[item] = 1;
}
else{
alname[item]++; //不是NaN就再加一
}
}
return alname.O === alname.X; //這裡回傳O跟X兩個 Key的Value有沒有一樣
} //一樣回傳true反之回傳false
雖然都可以解的出來,但如果追求精簡導致後來的自己看不懂就不好了!
我用索引讀取字元~
function XO(str) {
str = str.toUpperCase();
var ans = 0;
for(var i = 0; i < str.length; i++) {
if (str[i] === 'X')
ans--;
if (str[i] === 'O')
ans++;
}
return !ans;
}
好厲害
目前只學到用[x][0]抓到字首
沒想到可以這樣用
用 map
大概會是這樣
const XO = (str) => {
str = str.toUpperCase().split('');
let p = str[0];
let ans = 0;
str.map(x => x === p ? ans++ : ans-- )
return !!!ans
}
感覺用map比較簡單欸
// 這樣應該好讀易懂吧 (?
function XO(str) {
return !str.split('').reduce((acc, c) => {
if (c === 'O' || c === 'o' ) acc++
if (c === 'X' || c === 'x' ) acc--
return acc
}, 0)
}
// 犧牲可讀性的話
const XO = s => !s.split('').reduce(
(a, c) => ('Oo'.includes(c) ? ++a : 'Xx'.includes(c) ? --a : a)
, 0)
驚嘆號原來可以寫在最前面,我都被自己的思維綁住了!
我會先把非x,o的過濾
function XO(str) {
const strFormat = str.toLowerCase().replace(/[^o,x]/g,'').split('');
return strFormat.length - strFormat
.filter(letter => letter === 'x').length * 2 === 0;
}